package com.vtech.spring.config;

import com.vtech.spring.security.DbRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.crypto.hash.Sha512Hash;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Shiro 配置
 * http://shiro.apache.org/spring-boot.html
 *
 * @author houzhiwei
 * @date 2018/6/9 22:29
 */
@Configuration
public class ShiroConfiguration {

    /**
     * <pre>
     * 最简配置(不配置SecurityManager等)时必须返回 Realm，不能是DbRealm，否则报错：
     * Parameter 0 of method authorizationAttributeSourceAdvisor in
     * org.apache.shiro.spring.config.web.autoconfigure.ShiroAnnotationProcessorAutoConfiguration
     * required a bean named 'authorizer' that could not be found
     * </pre>
     * @return {@link Realm}
     */
    @Bean
    public Realm realm() {
        // 自己实现的 shiro 安全数据源
        DbRealm realm = new DbRealm();
        realm.setCredentialsMatcher(credentialsMatcher());
        // ...
        realm.setCachingEnabled(true);
        return realm;
    }

    /**
     * url 过滤配置
     * 自上而下过滤，采用短路机制
     *
     * @return
     */
    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();

        // 以 admin 角色登录的用户
        chainDefinition.addPathDefinition("/admin/**", "authc,roles[admin]");
        // chainDefinition.addPathDefinition("/**", "authc");
        return chainDefinition;
    }

    /**
     * 密码验证
     * 根据login时的 AuthenticationToken，以及 realm 中传递的信息进行匹配
     *
     * @return
     */
    @Bean
    public HashedCredentialsMatcher credentialsMatcher() {
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        // 16进制存储
        matcher.setStoredCredentialsHexEncoded(true);
        matcher.setHashAlgorithmName(Sha512Hash.ALGORITHM_NAME);
        matcher.setHashIterations(5);
        return matcher;
    }

    @Bean
    protected CacheManager cacheManager() {
        return new MemoryConstrainedCacheManager();
    }

}
